{
 "cells": [
  {
   "cell_type": "markdown",
   "metadata": {},
   "source": [
    "# BB84\n",
    "\n",
    "We are going to use Qiskit to simulate the BB84 protocol\n",
    "\n",
    "We will use the circuit from our previous notebook to generate random bits"
   ]
  },
  {
   "cell_type": "code",
   "execution_count": 2,
   "metadata": {},
   "outputs": [
    {
     "data": {
      "image/png": "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\n",
      "text/plain": [
       "<Figure size 233.576x144.48 with 1 Axes>"
      ]
     },
     "execution_count": 2,
     "metadata": {},
     "output_type": "execute_result"
    }
   ],
   "source": [
    "%matplotlib inline\n",
    "\n",
    "from qiskit import *\n",
    "from qiskit.visualization import *\n",
    "from qiskit.tools.monitor import *\n",
    "\n",
    "circ_random = QuantumCircuit(1,1) # We need qubit and one classical bit\n",
    "\n",
    "circ_random.h(0) #We apply the H gate\n",
    "\n",
    "circ_random.measure(range(1),range(1)) # Measure\n",
    "\n",
    "circ_random.draw(output='mpl')"
   ]
  },
  {
   "cell_type": "code",
   "execution_count": 3,
   "metadata": {
    "scrolled": true
   },
   "outputs": [
    {
     "name": "stdout",
     "output_type": "stream",
     "text": [
      "[0, 0, 0, 0, 1, 0, 0, 0, 0, 0, 1, 0, 1, 1, 0, 1, 1, 1, 0, 0, 0, 0, 0, 0, 0, 0, 0, 1, 0, 0, 1, 0, 0, 1, 1, 1, 0, 1, 1, 1, 1, 0, 0, 1, 0, 0, 1, 0, 1, 0, 1, 1, 1, 1, 0, 1, 0, 0, 0, 1, 1, 0, 0, 1, 0, 0, 0, 0, 0, 1, 1, 1, 1, 1, 0, 1, 0, 0, 0, 1, 1, 0, 1, 1, 0, 1, 0, 0, 1, 0, 0, 0, 1, 1, 0, 0, 1, 1, 0, 1]\n"
     ]
    }
   ],
   "source": [
    "n = 100 # Number of bits that we are going to use\n",
    "\n",
    "# Alice generates n random bits (some of these bits will form the key)\n",
    "\n",
    "backend = Aer.get_backend('qasm_simulator')\n",
    "job = execute(circ_random, backend, shots=n, memory = True) # We set the 'memory' parameter to true to be able to access the string of results\n",
    "bits_alice = [int(q) for q in job.result().get_memory()] \n",
    "print(bits_alice)"
   ]
  },
  {
   "cell_type": "code",
   "execution_count": 4,
   "metadata": {},
   "outputs": [
    {
     "name": "stdout",
     "output_type": "stream",
     "text": [
      "[1, 0, 0, 0, 0, 0, 1, 1, 0, 1, 0, 0, 0, 1, 0, 0, 1, 1, 1, 0, 0, 0, 0, 0, 0, 0, 0, 0, 1, 1, 1, 1, 1, 1, 1, 0, 1, 0, 1, 0, 1, 0, 1, 0, 0, 1, 1, 1, 1, 1, 1, 1, 0, 0, 1, 1, 1, 0, 1, 0, 1, 1, 1, 0, 1, 1, 0, 1, 1, 0, 1, 0, 0, 0, 1, 1, 1, 0, 1, 0, 0, 1, 1, 0, 0, 1, 0, 1, 1, 0, 1, 1, 1, 0, 1, 0, 0, 0, 0, 0]\n"
     ]
    }
   ],
   "source": [
    "# Alice randomly chooses the bases in which she is going to measure\n",
    "\n",
    "job = execute(circ_random, backend, shots=n, memory = True)\n",
    "basis_alice = [int(q) for q in job.result().get_memory()] \n",
    "print(basis_alice)"
   ]
  },
  {
   "cell_type": "code",
   "execution_count": 5,
   "metadata": {},
   "outputs": [
    {
     "name": "stdout",
     "output_type": "stream",
     "text": [
      "[1, 0, 0, 0, 1, 1, 1, 1, 1, 0, 1, 0, 1, 0, 1, 0, 1, 0, 1, 1, 0, 1, 1, 1, 1, 0, 1, 0, 0, 1, 0, 0, 1, 0, 1, 1, 1, 0, 1, 0, 1, 0, 0, 0, 0, 0, 0, 0, 1, 1, 0, 1, 0, 0, 0, 0, 0, 0, 0, 0, 1, 0, 1, 1, 0, 1, 0, 1, 0, 0, 0, 0, 1, 1, 0, 0, 1, 1, 0, 1, 0, 1, 0, 1, 0, 0, 0, 0, 1, 0, 0, 0, 1, 1, 0, 1, 1, 1, 1, 1]\n"
     ]
    }
   ],
   "source": [
    "# Bob also chooses at random the bases in which he will measure\n",
    "\n",
    "job = execute(circ_random, backend, shots=n, memory = True)\n",
    "basis_bob = [int(q) for q in job.result().get_memory()] \n",
    "print(basis_bob)"
   ]
  },
  {
   "cell_type": "code",
   "execution_count": 6,
   "metadata": {},
   "outputs": [
    {
     "name": "stdout",
     "output_type": "stream",
     "text": [
      "[0, 0, 0, 0, 0, 1, 0, 0, 1, 0, 1, 0, 0, 1, 1, 1, 1, 1, 0, 0, 0, 0, 1, 0, 0, 0, 1, 1, 0, 0, 0, 0, 0, 0, 1, 1, 0, 1, 1, 1, 1, 0, 1, 1, 0, 1, 0, 1, 1, 0, 1, 1, 1, 1, 0, 1, 1, 0, 0, 1, 1, 1, 0, 0, 0, 0, 0, 0, 1, 1, 1, 1, 0, 0, 0, 1, 0, 1, 1, 1, 1, 0, 1, 0, 0, 0, 0, 0, 1, 0, 0, 0, 1, 0, 0, 0, 1, 0, 0, 0]\n"
     ]
    }
   ],
   "source": [
    "# Now, Alice codes each bit of her initial string as a qubit and sends it to Bob, who measures in his basis\n",
    "\n",
    "bits_bob = []\n",
    "\n",
    "for i in range(n):\n",
    "    circ_send = QuantumCircuit(1,1)\n",
    "    if bits_alice[i]:  # Alice has to send '1'\n",
    "        circ_send.x(0)\n",
    "    if basis_alice[i]: # Alice codes in basis |+>, |->\n",
    "        circ_send.h(0)\n",
    "        \n",
    "    # Alice sends the qubit to Bob and he measures\n",
    "    \n",
    "    if basis_bob[i]: # Bob has to measure in basis |+>, |->\n",
    "        circ_send.h(0) \n",
    "    \n",
    "    circ_send.measure(0,0)\n",
    "    \n",
    "    job = execute(circ_send, backend, shots = 1, memory = True)\n",
    "    bits_bob.append(int(job.result().get_memory()[0]))\n",
    "    \n",
    "print(bits_bob)\n",
    "    "
   ]
  },
  {
   "cell_type": "code",
   "execution_count": 7,
   "metadata": {},
   "outputs": [
    {
     "name": "stdout",
     "output_type": "stream",
     "text": [
      "Key length 46\n",
      "[0, 0, 0, 0, 0, 0, 0, 1, 1, 0, 0, 0, 1, 0, 0, 1, 0, 1, 1, 1, 1, 0, 1, 0, 1, 0, 1, 1, 1, 0, 1, 1, 0, 0, 0, 0, 1, 1, 0, 1, 0, 0, 0, 1, 0, 1]\n"
     ]
    }
   ],
   "source": [
    "# Bob tells Alice the basis he used for his measurements \n",
    "# Alice confirms which of the basis are correct\n",
    "\n",
    "key = []\n",
    "\n",
    "for i in range(n):\n",
    "    if basis_alice[i] == basis_bob[i]:\n",
    "        key.append(bits_bob[i])\n",
    "        \n",
    "print(\"Key length\", len(key))\n",
    "print(key)"
   ]
  },
  {
   "cell_type": "code",
   "execution_count": null,
   "metadata": {},
   "outputs": [],
   "source": []
  }
 ],
 "metadata": {
  "kernelspec": {
   "display_name": "Python 3",
   "language": "python",
   "name": "python3"
  },
  "language_info": {
   "codemirror_mode": {
    "name": "ipython",
    "version": 3
   },
   "file_extension": ".py",
   "mimetype": "text/x-python",
   "name": "python",
   "nbconvert_exporter": "python",
   "pygments_lexer": "ipython3",
   "version": "3.8.2"
  }
 },
 "nbformat": 4,
 "nbformat_minor": 4
}
